/**
 * Copyright (c)  FESCOTech Team
 * All rights reserved.
 *
 * This file DataSourceConfiguration.java creation date: [2018年11月15日 上午8:37:19] by 姓名
 * http://www.fescoetc.com.cn
 */

package com.hdsxtech.smsoot_timer.common.datasource;

import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

/** 
 * <descption>配置并创建数据源</descption> 
 * @author mawen
 * @version 1.0.0
 */
@Configuration
public class DataSourceConfiguration {

	private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceConfiguration.class) ;
	
	@Autowired
	private Environment env;
	
	@Value("${jdbc.type}")
	private Class<? extends DataSource> dataSourceType;
	
	@Bean(name="masterDataSource")
	@ConfigurationProperties(prefix="master.jdbc")
	@Primary
	public  DataSource masterDataSource(){
		DataSource masterDataSource = DataSourceBuilder.create().type(dataSourceType).build();
		LOGGER.info("========= MASTER :{} =======",masterDataSource);
		return masterDataSource;
	}
	
	@Bean(name="slaveDataSource")
	@ConfigurationProperties(prefix="slave.jdbc")
	public DataSource slaveDataSource(){
		DataSource slaveDataSource = DataSourceBuilder.create().type(dataSourceType).build();
		LOGGER.info("========= SLAVE :{} ========",slaveDataSource);
		return slaveDataSource;
	}
	
	/**
	 * @Primary 给注解表示在同一个接口有多个实现类可以注入的时候，默认选择那个，而不是让@Autowied 注解报错
	 * @Qualifier 根据名称进行注入，通常是在具有相同的多个类型的实力的一个注入（列如有多个DataSource 的类型）
	 */
	@Bean
	public DynamicDataSource dataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
			@Qualifier("slaveDataSource") DataSource slaveDataSource){
		Map<Object,Object> targetDataSources = new HashMap<>();
		targetDataSources.put(DatabaseType.MASTER, masterDataSource);
		targetDataSources.put(DatabaseType.SLAVE, slaveDataSource);
		
		DynamicDataSource dataSource = new DynamicDataSource();
		dataSource.setTargetDataSources(targetDataSources); // 给方法是AbstractRoutingDataSource 的方法
		dataSource.setDefaultTargetDataSource(masterDataSource); // 默认的datasource 设置为  masterDataSource
		return dataSource;
	}
	
	/**
	 * 
	 * <descption> 根据数据源创建SqlSessionFactory </descption>
	 * 
	 * @param 
	 * @return
	 * @throws Exception 
	 */
	@Bean
	public SqlSessionFactory seqSessionFactory(DynamicDataSource ds) throws Exception{
		SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
		fb.setDataSource(ds);  // 指定数据源（这个必须有，否则报错）
		
		// 下边这两句仅仅用于*.xml文件，如果这个持久层操作不需要使用的xml 的话（只用注解就可以搞定） ，则不加
		fb.setTypeAliasesPackage("mybatis.typeAliasesPackage");  // 指定基包
		fb.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(env.getProperty("mybatis.mapper-locations")));
		return fb.getObject();
	}
	
	/**
	 * 
	 * <descption> 配置事务管理 </descption>
	 * 
	 * @param 
	 * @return
	 */
	@Bean
	public DataSourceTransactionManager tracsactionManager(DynamicDataSource ds){
		return new DataSourceTransactionManager(ds);
	}
}
